home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-09-28 | 9.3 KB | 335 lines | [TEXT/MPS ] |
- /*
- File: SoundHandler.c
-
- Contains: xxx put contents here xxx
-
- Version: xxx put version here xxx
-
- Copyright: © 1998-1999 by Apple Computer, Inc., all rights reserved.
-
- File Ownership:
-
- DRI: Chris De Salvo
-
- Other Contact: xxx put other contact here xxx
-
- Technology: Apple Game Sprockets
-
- Writers:
-
- (cjd) Chris De Salvo
- (cjd) Chris DeSalvo
-
- Change History (most recent first):
-
- <SP12> 7/1/99 cjd The camera and the point of interest were set to the same point.
- Bad. So we now push in the Z of the POI and pull back the Z of
- the camera.
- <SP11> 6/30/99 cjd The camera and the point of interest were set to the same point.
- Bad. So we now push in the Z of the POI and pull back the Z of
- the camera.
- <SP10> 1/21/99 cjd Removing 68K conditional
- <9> 7/1/98 cjd Added SSp CPU load throttling
- */
-
- //• ------------------------------------------------------------------------------------------ •
- //•
- //• Copyright © 1996 Apple Computer, Inc., All Rights Reserved
- //•
- //•
- //• You may incorporate this sample code into your applications without
- //• restriction, though the sample code has been provided "AS IS" and the
- //• responsibility for its operation is 100% yours. However, what you are
- //• not permitted to do is to redistribute the source as "DSC Sample Code"
- //• after having made changes. If you're going to re-distribute the source,
- //• we require that you make it clear in the source that the code was
- //• descended from Apple Sample Code, but that you've made changes.
- //•
- //• Authors:
- //• Chris De Salvo
- //• Tim Carroll
- //•
- //• ------------------------------------------------------------------------------------------ •
-
- //• ------------------------------ Includes
-
- #include <Resources.h>
- #include <Sound.h>
- #include <SoundSprocket.h>
- #include <SoundComponents.h>
- #include <CodeFragments.h>
-
- #include "ErrorHandler.h"
- #include "EventHandler.h"
- #include "MemoryHandler.h"
- #include "SIResources.h"
- #include "SoundHandler.h"
-
- //• ------------------------------ Private Definitions
- //• ------------------------------ Private Types
- //• ------------------------------ Private Variables
-
- static Boolean gSoundHandlerInit = false;
- static SndChannelPtr gChannels[soundNumSounds];
- static Handle gSounds[soundNumSounds];
- static SSpSourceReference gSource[soundNumSounds];
- static SSpListenerReference gListener;
- static Boolean gSoundSprocket = false;
-
- //• ------------------------------ Private Functions
-
- static void SetListenerLocation(const SInt32 inPOI_X, const SInt32 inPOI_Y);
-
- //• ------------------------------ Public Variables
-
- Boolean gSoundEffects = true;
-
- UInt32 gCPULoadModifier = 0;
- UInt32 gCPULoadMax = 0;
- UInt32 gCPUCurrentLoad = 0;
-
- //• -------------------- SoundHandlerInit
-
- void
- SoundHandlerInit(void)
- {
- UInt32 i;
-
- gSoundSprocket = false;
-
- //• Allocate the sound channels for playback
- for (i = 0; i < soundNumSounds; i++)
- {
- OSErr theErr;
-
- theErr = SndNewChannel(&gChannels[i], sampledSynth, initMono, nil);
- if (theErr)
- FatalError("Could not allocate enough sound channels.");
- }
-
- //• Load the actual sound effects
- for (i = 0; i < soundNumSounds; i++)
- {
- gSounds[i] = GetResource('snd ', kSND_PlayerFire + i);
- if (! gSounds[i])
- FatalError("Could not load a required sound effect.");
-
- DetachResource(gSounds[i]);
- }
-
- gSoundHandlerInit = true;
-
- //• If SoundSprocket is present then create a listener and set things up
- if ((Ptr) SSpConfigureSpeakerSetup == (Ptr) kUnresolvedCFragSymbolAddress)
- {
- return; // no sound sprocket
- }
- else
- {
- OSStatus theErr = noErr;
-
- theErr = SSpGetCPULoadLimit(&gCPULoadMax);
-
- if (noErr != theErr)
- {
- //• If we couldn't figure out the number of steps then we'll
- //• just set the CPU load to zero every time. This forces maximum quality.
- gCPULoadModifier = 0;
- }
- else
- {
- gCPULoadModifier = 0xFFFFFFFF / (gCPULoadMax + 1);
- }
-
- //• We have sound sprocket, so now we install the filters and create source and listener objects.
-
- //• Create the listener
- theErr = SSpListener_New(&gListener);
- if (theErr)
- FatalError("Could not create a sound sprocket listener.");
-
- //• Define our unit of distance measurement
- theErr = SSpListener_SetMetersPerUnit(gListener, 0.05);
- if (theErr)
- FatalError ("Could not set reference distance for listener.");
-
- //• Attach the sound localization component to each of the sound
- //• channels that we'll be playing through.
- for (i = 0; i < soundNumSounds; i++)
- {
- SoundComponentLink myLink;
-
- //• Create the source
- theErr = SSpSource_New(&gSource[i]);
- if (theErr)
- FatalError("Could not create a sound sprocket source.");
-
- //• Install the filter
- myLink.description.componentType = kSoundEffectsType;
- myLink.description.componentSubType = kSSpLocalizationSubType;
- myLink.description.componentManufacturer = 0;
- myLink.description.componentFlags = 0;
- myLink.description.componentFlagsMask = 0;
- myLink.mixerID = nil;
- myLink.linkID = nil;
-
- theErr = SndSetInfo(gChannels[i], siPreMixerSoundComponent, &myLink);
- if (theErr)
- FatalError("Could not install the sound sprocket filter into the channel.");
- }
-
- gSoundSprocket = true;
- SetListenerLocation(320, 240);
- }
- }
-
- //• -------------------- SoundHandlerReset
-
- void
- SoundHandlerReset(void)
- {
- UInt32 i;
-
- if (! gSoundHandlerInit)
- return;
-
- //• Deallocate the sound channels
- for (i = 0; i < soundNumSounds; i++)
- {
- if (gChannels[i])
- {
- SndDisposeChannel(gChannels[i], true);
- gChannels[i] = nil;
- }
- }
-
- //• Unload the actual sound effects
- for (i = 0; i < soundNumSounds; i++)
- {
- if (gSounds[i])
- DisposeHandleZ(&gSounds[i]);
- }
-
- }
-
- //• -------------------- SoundHandlerPlay
-
- void
- SoundHandlerPlay(GameSounds theSound, short x, short y)
- {
- SndCommand theCommand;
- OSStatus theErr = noErr;
-
- //• Make sure that sound effects are turned on
- if (! gSoundEffects)
- return;
-
- //• Make sure we are initialized
- if (! gSoundHandlerInit)
- return;
-
- //• Make sure the requested sound is within the range of valid effects
- if (theSound < 0 || theSound >= soundNumSounds)
- return;
-
- //• Stop playback of any sound currently playing on this channel
- theCommand.cmd = quietCmd;
- SndDoImmediate(gChannels[theSound], &theCommand);
-
- //• Flush out any queued sounds waiting to play on this channel
- theCommand.cmd = flushCmd;
- SndDoImmediate(gChannels[theSound], &theCommand);
-
- //• If we're using SoundSprocket then set up the location parameters
- //• for the localization filter
- if (gSoundSprocket)
- {
- TQ3CameraPlacement location;
- SSpLocalizationData localization;
-
- //• We want all the sounds to be localized, but when we explode we want to hear it
- //• all around us.
- if (soundPlayerHit != theSound)
- SSpSource_SetMode(gSource[theSound], kSSpSourceMode_Localized);
- else
- SSpSource_SetMode(gSource[theSound], kSSpSourceMode_Ambient);
-
- //• Allow the user to dynamically set the CPU usage range for SSp
- SSpSource_SetCPULoad(gSource[theSound], gCPUCurrentLoad);
-
- //• Make sure that the listener is listening at this sound
- SetListenerLocation(320 - x, 240 - y);
-
- //• Position the sound in space.
- location.cameraLocation.x = 320 - x;
- location.cameraLocation.y = 240 - y;
- location.cameraLocation.z = 0;
-
- //• Orient the sound so that it is down directed down towards the listener
- location.pointOfInterest.x = 0;
- location.pointOfInterest.y = -1;
- location.pointOfInterest.z = -1;
-
- location.upVector.x = 0;
- location.upVector.y = 1;
- location.upVector.z = 0;
-
- theErr = SSpSource_SetCameraPlacement (gSource[theSound], &location);
- if (theErr)
- FatalError ("Failed to set the source location");
-
- theErr = SSpSource_CalcLocalization (gSource[theSound], gListener, &localization);
- if (theErr)
- FatalError ("Failed to calculate the localization");
-
- // We don't do doppler, since we only localize the sound at the instant it is played.
- localization.currentLocation.sourceVelocity = 0;
- localization.currentLocation.listenerVelocity = 0;
-
- // We set the reference distance to a reasonable number that seems to get good results
- // We also provide a minimum distance or else we run into really LOUD, really CLIPPED sounds
- localization.referenceDistance = 20.0;
- if (localization.currentLocation.distance < 5.0)
- localization.currentLocation.distance = 5.0;
-
- theErr = SndSetInfo (gChannels[theSound], siSSpLocalization, &localization);
- if (theErr)
- FatalError("Failed to localize the channel");
- }
-
- //• Play the selected sound immediately
- theErr = SndPlay(gChannels[theSound], (SndListHandle) gSounds[theSound], true);
- if (theErr)
- FatalError("Failed to start sound in SndPlay().");
- }
-
- //• -------------------- SetListenerLocation
-
- static void
- SetListenerLocation(const SInt32 inPOI_X, const SInt32 inPOI_Y)
- {
- OSStatus theErr = noErr;
- TQ3CameraPlacement location;
-
- if (! gSoundSprocket)
- return;
-
- //• Set the listener in the bottom middle of the screen
- location.cameraLocation.x = 320;
- location.cameraLocation.y = 240;
- location.cameraLocation.z = -10;
-
- //• Focus the listener's attention on the exact middle of the screen
- location.pointOfInterest.x = inPOI_X;
- location.pointOfInterest.y = inPOI_Y;
- location.pointOfInterest.z = 0;
-
- location.upVector.x = 0;
- location.upVector.y = 1;
- location.upVector.z = 0;
-
- theErr = SSpListener_SetCameraPlacement (gListener, &location);
- if (theErr)
- FatalError ("Failed to set the listener location");
- }
-